<template>
  <div class="min-h-screen flex flex-col">
    <!-- 顶部导航 -->
    <header class="bg-white shadow-md z-10">
      <div class="container mx-auto px-4 py-3 flex justify-between items-center">
        <div class="flex items-center space-x-2">
          <i class="fa fa-cubes text-primary text-2xl"></i>
          <h1 class="text-xl font-bold text-neutral">钢坯加热温度分布3D可视化</h1>
        </div>
        <div class="flex items-center space-x-4">
          <button class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg transition-custom flex items-center">
            <i class="fa fa-download mr-2"></i>导出数据
          </button>
          <button class="bg-gray-200 hover:bg-gray-300 text-neutral px-4 py-2 rounded-lg transition-custom flex items-center">
            <i class="fa fa-question-circle mr-2"></i>帮助
          </button>
        </div>
      </div>
    </header>

    <!-- 主要内容区 -->
    <main class="flex-1 flex flex-col md:flex-row">
      <!-- 左侧控制面板 -->
      <aside class="w-full md:w-64 bg-white shadow-md p-4 space-y-4">
        <div class="space-y-2">
          <h2 class="font-bold text-lg text-neutral border-b pb-2">可视化控制</h2>
          <div class="space-y-4">
            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">视角</label>
              <div class="grid grid-cols-3 gap-2">
                <button @click="setView('front')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-up"></i> 前
                </button>
                <button @click="setView('back')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-down"></i> 后
                </button>
                <button @click="setView('top')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-right"></i> 顶
                </button>
                <button @click="setView('bottom')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-left"></i> 底
                </button>
                <button @click="setView('left')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-left"></i> 左
                </button>
                <button @click="setView('right')" class="bg-gray-200 hover:bg-gray-300 p-2 rounded transition-custom">
                  <i class="fa fa-arrow-right"></i> 右
                </button>
              </div>
            </div>

            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">温度范围</label>
              <div class="flex items-center space-x-2">
                <span class="text-xs text-gray-500">{{ Math.round(minTemp) }}°C</span>
                <input type="range" v-model.number="tempRange" min="1" max="10" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-primary">
                <span class="text-xs text-gray-500">{{ Math.round(maxTemp) }}°C</span>
              </div>
            </div>

            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">显示网格</label>
              <div class="flex items-center">
                <input type="checkbox" id="showGrid" v-model="showGrid" class="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded">
                <label for="showGrid" class="ml-2 block text-sm text-gray-700">启用</label>
              </div>
            </div>

            <div>
              <label class="block text-sm font-medium text-gray-700 mb-1">显示坐标轴</label>
              <div class="flex items-center">
                <input type="checkbox" id="showAxes" v-model="showAxes" class="h-4 w-4 text-primary focus:ring-primary border-gray-300 rounded">
                <label for="showAxes" class="ml-2 block text-sm text-gray-700">启用</label>
              </div>
            </div>
          </div>
        </div>

        <div class="space-y-2">
          <h2 class="font-bold text-lg text-neutral border-b pb-2">温度信息</h2>
          <div class="bg-gray-100 p-3 rounded-lg">
            <div class="flex justify-between text-sm">
              <span class="text-gray-600">当前位置:</span>
              <span class="font-medium">{{ hoverPosition }}</span>
            </div>
            <div class="flex justify-between text-sm mt-1">
              <span class="text-gray-600">温度:</span>
              <span class="font-medium text-red-600">{{ hoverTemperature }}°C</span>
            </div>
            <div class="flex justify-between text-sm mt-1">
              <span class="text-gray-600">平均温度:</span>
              <span class="font-medium">{{ averageTemperature.toFixed(1) }}°C</span>
            </div>
            <div class="flex justify-between text-sm mt-1">
              <span class="text-gray-600">最高温度:</span>
              <span class="font-medium text-red-600">{{ maxTemperature.toFixed(1) }}°C</span>
            </div>
            <div class="flex justify-between text-sm mt-1">
              <span class="text-gray-600">最低温度:</span>
              <span class="font-medium text-blue-600">{{ minTemperature.toFixed(1) }}°C</span>
            </div>
          </div>
        </div>
      </aside>

      <!-- 中央3D视图区 -->
      <section class="flex-1 relative bg-gray-100">
        <div id="visualization-container" ref="visualizationContainer" class="w-full h-full"></div>

        <!-- 温度图例 -->
        <div class="absolute bottom-4 right-4 bg-white/90 p-3 rounded-lg shadow-lg z-10">
          <h3 class="font-medium text-sm mb-2">温度图例</h3>
          <div class="flex flex-col space-y-1">
            <div class="flex items-center">
              <div class="w-3 h-3 bg-blue-500 rounded-full mr-2"></div>
              <span class="text-xs text-gray-700">{{ Math.round(minTemp) }}°C</span>
            </div>
            <div class="flex items-center">
              <div class="w-3 h-3 bg-green-500 rounded-full mr-2"></div>
              <span class="text-xs text-gray-700">{{ Math.round(minTemp + (maxTemp - minTemp) * 0.25) }}°C</span>
            </div>
            <div class="flex items-center">
              <div class="w-3 h-3 bg-yellow-500 rounded-full mr-2"></div>
              <span class="text-xs text-gray-700">{{ Math.round(minTemp + (maxTemp - minTemp) * 0.5) }}°C</span>
            </div>
            <div class="flex items-center">
              <div class="w-3 h-3 bg-orange-500 rounded-full mr-2"></div>
              <span class="text-xs text-gray-700">{{ Math.round(minTemp + (maxTemp - minTemp) * 0.75) }}°C</span>
            </div>
            <div class="flex items-center">
              <div class="w-3 h-3 bg-red-500 rounded-full mr-2"></div>
              <span class="text-xs text-gray-700">{{ Math.round(maxTemp) }}°C</span>
            </div>
          </div>
        </div>

        <!-- 操作说明 -->
        <div class="absolute top-4 right-4 bg-white/90 p-3 rounded-lg shadow-lg z-10">
          <h3 class="font-medium text-sm mb-2">操作说明</h3>
          <ul class="text-xs text-gray-700 space-y-1">
            <li><i class="fa fa-arrows mr-1"></i> 拖拽: 旋转视角</li>
            <li><i class="fa fa-search-plus mr-1"></i> 滚轮: 缩放</li>
            <li><i class="fa fa-hand-paper-o mr-1"></i> Shift+拖拽: 平移</li>
            <li><i class="fa fa-mouse-pointer mr-1"></i> 鼠标悬停: 显示温度信息</li>
          </ul>
        </div>
      </section>
    </main>

    <!-- 页脚 -->
    <footer class="bg-white shadow-inner py-4">
      <div class="container mx-auto px-4 text-center text-sm text-gray-600">
        <p>© 2025 钢坯温度可视化系统 | 技术支持: 工艺控制部</p>
      </div>
    </footer>
  </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export default {
  name: 'SteelTemperatureVisualization',
  data() {
    return {
      // 钢坯尺寸
      steelWidth: 10,
      steelHeight: 5,
      steelDepth: 8,

      // 温度数据
      temperatureData: null,
      tempRange: 5,
      minTemp: 0,
      maxTemp: 0,
      hoverPosition: '未选择',
      hoverTemperature: '0',

      // 视图控制
      showGrid: true,
      showAxes: true,

      // Three.js相关对象
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      steelBillet: null,
      gridHelper: null,
      axesHelper: null,
      points: null,

      // 交互相关
      raycaster: null,
      mouse: new THREE.Vector2()
    };
  },
  computed: {
    // 计算温度范围
    adjustedMinTemp() {
      return this.temperatureData.min - (this.tempRange - 5) * 20;
    },
    adjustedMaxTemp() {
      return this.temperatureData.max + (this.tempRange - 5) * 20;
    },
    // 统计数据
    averageTemperature() {
      return this.temperatureData ? this.temperatureData.average : 0;
    },
    maxTemperature() {
      return this.temperatureData ? this.temperatureData.max : 0;
    },
    minTemperature() {
      return this.temperatureData ? this.temperatureData.min : 0;
    }
  },
  mounted() {
    // 生成温度数据
    this.generateTemperatureData();

    // 初始化3D场景
    this.$nextTick(() => {
      this.initScene();
    });

    // 监听窗口大小变化
    window.addEventListener('resize', this.handleResize);
  },
  beforeDestroy() {
    // 移除事件监听器
    window.removeEventListener('resize', this.handleResize);
    this.$refs.visualizationContainer.removeEventListener('mousemove', this.onMouseMove);
    this.$refs.visualizationContainer.removeEventListener('click', this.onClick);

    // 清理Three.js资源
    if (this.renderer) {
      this.renderer.dispose();
    }
  },
  methods: {
    // 温度数据生成函数
    generateTemperatureData() {
      const data = [];
      let sum = 0;
      let count = 0;
      let maxTemp = -Infinity;
      let minTemp = Infinity;

      // 模拟钢坯温度分布（边缘温度低，中心温度高）
      for (let x = 0; x < this.steelWidth; x++) {
        data[x] = [];
        for (let y = 0; y < this.steelHeight; y++) {
          data[x][y] = [];
          for (let z = 0; z < this.steelDepth; z++) {
            // 计算到中心的相对距离
            const centerX = this.steelWidth / 2;
            const centerY = this.steelHeight / 2;
            const centerZ = this.steelDepth / 2;

            const distX = Math.abs(x - centerX) / centerX;
            const distY = Math.abs(y - centerY) / centerY;
            const distZ = Math.abs(z - centerZ) / centerZ;
            const maxDist = Math.max(distX, distY, distZ);

            // 基础温度
            const baseTemp = 1200;
            // 温度波动
            const fluctuation = 50 * (0.5 - Math.random());
            // 边缘冷却效应
            const edgeCooling = 200 * maxDist;

            const temp = baseTemp - edgeCooling + fluctuation;

            data[x][y][z] = temp;

            // 更新统计信息
            sum += temp;
            count++;
            if (temp > maxTemp) maxTemp = temp;
            if (temp < minTemp) minTemp = temp;
          }
        }
      }

      this.temperatureData = {
        data,
        average: sum / count,
        max: maxTemp,
        min: minTemp
      };

      // 设置初始温度范围
      this.minTemp = this.temperatureData.min - 100;
      this.maxTemp = this.temperatureData.max + 100;
    },

    // 温度到颜色的映射函数
    temperatureToColor(temp, minTemp, maxTemp) {
      const normalizedTemp = Math.max(0, Math.min(1, (temp - minTemp) / (maxTemp - minTemp)));

      // 从蓝色到红色的渐变
      let r, g, b;

      if (normalizedTemp < 0.25) {
        r = 0;
        g = 4 * normalizedTemp;
        b = 1;
      } else if (normalizedTemp < 0.5) {
        r = 0;
        g = 1;
        b = 1 - 4 * (normalizedTemp - 0.25);
      } else if (normalizedTemp < 0.75) {
        r = 4 * (normalizedTemp - 0.5);
        g = 1;
        b = 0;
      } else {
        r = 1;
        g = 1 - 4 * (normalizedTemp - 0.75);
        b = 0;
      }

      return new THREE.Color(r, g, b);
    },

    // 初始化3D场景
    initScene() {
      const container = this.$refs.visualizationContainer;

      // 创建场景
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0xf0f0f0);

      // 创建相机
      const aspect = container.clientWidth / container.clientHeight;
      this.camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000);
      this.camera.position.set(15, 10, 15);

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(container.clientWidth, container.clientHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      container.appendChild(this.renderer.domElement);

      // 添加轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      this.controls.enablePan = true;
      this.controls.panSpeed = 0.5;

      // 添加光源
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
      this.scene.add(ambientLight);

      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
      directionalLight.position.set(1, 1, 1);
      this.scene.add(directionalLight);

      const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.4);
      directionalLight2.position.set(-1, -1, -1);
      this.scene.add(directionalLight2);

      // 添加网格辅助线
      this.gridHelper = new THREE.GridHelper(20, 20, 0xcccccc, 0xcccccc);
      this.gridHelper.visible = this.showGrid;
      this.scene.add(this.gridHelper);

      // 添加坐标轴辅助线
      this.axesHelper = new THREE.AxesHelper(10);
      this.axesHelper.visible = this.showAxes;
      this.scene.add(this.axesHelper);

      // 创建钢坯几何体
      const geometry = new THREE.BoxGeometry(this.steelWidth, this.steelHeight, this.steelDepth);

      // 创建材质数组（每个面一种材质）
      const materials = [];
      for (let i = 0; i < 6; i++) {
        materials.push(new THREE.MeshPhongMaterial({
          color: 0x888888,
          transparent: true,
          opacity: 0.9,
          side: THREE.FrontSide,
          flatShading: true
        }));
      }

      // 创建钢坯网格
      this.steelBillet = new THREE.Mesh(geometry, materials);
      this.steelBillet.position.set(0, this.steelHeight/2, 0);
      this.scene.add(this.steelBillet);

      // 添加边缘线
      const edges = new THREE.EdgesGeometry(geometry);
      const lineMaterial = new THREE.LineBasicMaterial({ color: 0x333333, linewidth: 1 });
      const wireframe = new THREE.LineSegments(edges, lineMaterial);
      this.steelBillet.add(wireframe);

      // 创建温度数据可视化点
      this.createTemperaturePoints();

      // 初始化射线检测
      this.raycaster = new THREE.Raycaster();

      // 添加事件监听器
      container.addEventListener('mousemove', this.onMouseMove, false);
      container.addEventListener('click', this.onClick, false);

      // 开始动画循环
      this.animate();
    },

    // 创建温度点云
    createTemperaturePoints() {
      const pointGeometry = new THREE.BufferGeometry();
      const positions = [];
      const colors = [];
      const sizes = [];

      const pointCount = 5000; // 显示的点数量

      for (let i = 0; i < pointCount; i++) {
        // 随机位置
        const x = (Math.random() - 0.5) * this.steelWidth;
        const y = Math.random() * this.steelHeight;
        const z = (Math.random() - 0.5) * this.steelDepth;

        // 转换为数据索引
        const dataX = Math.floor(((x / this.steelWidth) + 0.5) * this.temperatureData.data.length);
        const dataY = Math.floor((y / this.steelHeight) * this.temperatureData.data[0].length);
        const dataZ = Math.floor(((z / this.steelDepth) + 0.5) * this.temperatureData.data[0][0].length);

        // 确保索引在范围内
        const clampedX = Math.max(0, Math.min(dataX, this.temperatureData.data.length - 1));
        const clampedY = Math.max(0, Math.min(dataY, this.temperatureData.data[0].length - 1));
        const clampedZ = Math.max(0, Math.min(dataZ, this.temperatureData.data[0][0].length - 1));

        // 获取温度
        const temp = this.temperatureData.data[clampedX][clampedY][clampedZ];

        // 添加位置
        positions.push(x, y, z);

        // 添加颜色
        const color = this.temperatureToColor(temp, this.minTemp, this.maxTemp);
        colors.push(color.r, color.g, color.b);

        // 添加大小（温度越高，点越大）
        const normalizedTemp = (temp - this.minTemp) / (this.maxTemp - this.minTemp);
        sizes.push(0.1 + 0.3 * normalizedTemp);
      }

      // 设置几何体属性
      pointGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
      pointGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
      pointGeometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1));

      // 创建点材质
      const pointMaterial = new THREE.PointsMaterial({
        size: 0.2,
        vertexColors: true,
        transparent: true,
        opacity: 0.8
      });

      // 创建点云
      this.points = new THREE.Points(pointGeometry, pointMaterial);
      this.points.position.set(0, this.steelHeight/2, 0);
      this.scene.add(this.points);
    },

    // 更新温度点云
    updateTemperaturePoints() {
      if (!this.points) return;

      const pointGeometry = this.points.geometry;
      const colorAttribute = pointGeometry.attributes.color;
      const sizeAttribute = pointGeometry.attributes.size;

      const pointCount = 5000; // 显示的点数量

      for (let i = 0; i < pointCount; i++) {
        // 随机位置
        const x = (Math.random() - 0.5) * this.steelWidth;
        const y = Math.random() * this.steelHeight;
        const z = (Math.random() - 0.5) * this.steelDepth;

        // 转换为数据索引
        const dataX = Math.floor(((x / this.steelWidth) + 0.5) * this.temperatureData.data.length);
        const dataY = Math.floor((y / this.steelHeight) * this.temperatureData.data[0].length);
        const dataZ = Math.floor(((z / this.steelDepth) + 0.5) * this.temperatureData.data[0][0].length);

        // 确保索引在范围内
        const clampedX = Math.max(0, Math.min(dataX, this.temperatureData.data.length - 1));
        const clampedY = Math.max(0, Math.min(dataY, this.temperatureData.data[0].length - 1));
        const clampedZ = Math.max(0, Math.min(dataZ, this.temperatureData.data[0][0].length - 1));

        // 获取温度
        const temp = this.temperatureData.data[clampedX][clampedY][clampedZ];

        // 更新颜色
        const color = this.temperatureToColor(temp, this.minTemp, this.maxTemp);
        colorAttribute.setXYZ(i, color.r, color.g, color.b);

        // 更新大小
        const normalizedTemp = (temp - this.minTemp) / (this.maxTemp - this.minTemp);
        sizeAttribute.setX(i, 0.1 + 0.3 * normalizedTemp);
      }

      colorAttribute.needsUpdate = true;
      sizeAttribute.needsUpdate = true;
    },

    // 鼠标移动事件
    onMouseMove(event) {
      const container = this.$refs.visualizationContainer;
      // 计算鼠标在标准化设备坐标中的位置 (-1 to +1)
      this.mouse.x = (event.clientX / container.clientWidth) * 2 - 1;
      this.mouse.y = -(event.clientY / container.clientHeight) * 2 + 1;
    },

    // 鼠标点击事件
    onClick(event) {
      // 更新射线
      this.raycaster.setFromCamera(this.mouse, this.camera);

      // 计算射线与场景中物体的交点
      const intersects = this.raycaster.intersectObject(this.steelBillet);

      if (intersects.length > 0) {
        const intersection = intersects[0];

        // 获取交点的世界坐标
        const worldPosition = intersection.point.clone();

        // 转换为钢坯局部坐标
        const localPosition = worldPosition.clone().sub(this.steelBillet.position);

        // 转换为温度数据索引
        const dataX = Math.floor(((localPosition.x / this.steelWidth) + 0.5) * this.temperatureData.data.length);
        const dataY = Math.floor((localPosition.y / this.steelHeight) * this.temperatureData.data[0].length);
        const dataZ = Math.floor(((localPosition.z / this.steelDepth) + 0.5) * this.temperatureData.data[0][0].length);

        // 确保索引在范围内
        const clampedX = Math.max(0, Math.min(dataX, this.temperatureData.data.length - 1));
        const clampedY = Math.max(0, Math.min(dataY, this.temperatureData.data[0].length - 1));
        const clampedZ = Math.max(0, Math.min(dataZ, this.temperatureData.data[0][0].length - 1));

        // 获取温度
        const temp = this.temperatureData.data[clampedX][clampedY][clampedZ];

        // 更新悬停信息
        this.hoverPosition = `(${localPosition.x.toFixed(2)}, ${localPosition.y.toFixed(2)}, ${localPosition.z.toFixed(2)})`;
        this.hoverTemperature = temp.toFixed(1);
      }
    },

    // 动画循环
    animate() {
      requestAnimationFrame(this.animate);

      // 更新控制器
      if (this.controls) {
        this.controls.update();
      }

      // 渲染场景
      if (this.renderer && this.scene && this.camera) {
        this.renderer.render(this.scene, this.camera);
      }
    },

    // 设置视角
    setView(view) {
      if (!this.camera || !this.controls) return;

      switch(view) {
        case 'front':
          this.camera.position.set(0, 5, 15);
          break;
        case 'back':
          this.camera.position.set(0, 5, -15);
          break;
        case 'top':
          this.camera.position.set(0, 15, 0);
          break;
        case 'bottom':
          this.camera.position.set(0, -15, 0);
          break;
        case 'left':
          this.camera.position.set(-15, 5, 0);
          break;
        case 'right':
          this.camera.position.set(15, 5, 0);
          break;
      }
      this.controls.target.set(0, this.steelHeight/2, 0);
      this.controls.update();
    },

    // 处理窗口大小变化
    handleResize() {
      if (!this.camera || !this.renderer) return;

      const container = this.$refs.visualizationContainer;
      this.camera.aspect = container.clientWidth / container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(container.clientWidth, container.clientHeight);
    }
  },
  watch: {
    // 监听温度范围变化
    tempRange() {
      this.minTemp = this.adjustedMinTemp;
      this.maxTemp = this.adjustedMaxTemp;
      this.updateTemperaturePoints();
    },

    // 监听网格显示状态变化
    showGrid(newValue) {
      if (this.gridHelper) {
        this.gridHelper.visible = newValue;
      }
    },

    // 监听坐标轴显示状态变化
    showAxes(newValue) {
      if (this.axesHelper) {
        this.axesHelper.visible = newValue;
      }
    }
  }
};
</script>

<style scoped>
.transition-custom {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.text-primary {
  color: #3b82f6;
}

.text-secondary {
  color: #f97316;
}

.text-neutral {
  color: #1f2937;
}
</style>